package com.example.windswing;

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.util.Log;
import android.widget.Toast;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.UnknownHostException;

public class WindSwingService extends Service {
    private DatagramSocket socket;
    private Handler handler = new Handler(Looper.getMainLooper());

    private UDPRecv udpRecv;
    private UDPSend udpSend;

    private String localIP;

    private String windSwingIP;
    private int windSwingPort;
    private InetSocketAddress windSwingSocketAddress;

    /*==bind service==*/
    @Override
    public IBinder onBind(Intent intent) {
        return new ServiceBinder();
    }

    public class ServiceBinder extends Binder{
        WindSwingService getService(){
            return WindSwingService.this;
        }
    }

    public DatagramSocket createDatagramSocket(String localIP){
        this.localIP = localIP;
        try {
            InetSocketAddress address = new InetSocketAddress(localIP, 9090);
            socket = new DatagramSocket(address);
        }catch (Exception e){
            Log.e("MY", "创建DatagramSocket失败", e);
            return null;
        }
        return socket;
    }

    public DatagramSocket getSocket() {
        return socket;
    }

    public void setWindSwingAddress(String ip, int port){
        this.windSwingIP = ip;
        this.windSwingPort = port;
        windSwingSocketAddress = new InetSocketAddress(ip, port);
    }

    public boolean createUDPThreads(){
        if(udpRecv == null){
            if(socket != null) {
                udpRecv = new UDPRecv(socket);
            }else{
                Log.e("MY", "未创建DatagramSocket");
                return false;
            }
        }
        if(udpSend == null) {
            if(socket != null){
                udpSend = new UDPSend(this, socket);
            }else{
                Log.e("MY", "未创建DatagramSocket");
                return false;
            }
        }
        return true;
    }

    public void setUdpRecvOnReceiveListener(UDPRecv.OnReceivedListener listener){
        if(udpRecv != null){
            udpRecv.setOnReceivedListener(listener);
        }
    }

    public void startUDPRecvThreads(){
        if(udpRecv != null && !udpRecv.started){
            udpRecv.start();
        }
    }

    public void sendData(byte[] data){
        udpSend.sendData(data, windSwingSocketAddress);
    }

    public void toast(CharSequence string, int duration){
        handler.post(() -> {
            Toast.makeText(getApplicationContext(), string, duration).show();
        });
    }

    public static class UDPRecv extends Thread{
        private DatagramSocket socket;
        private DatagramPacket packet;
        public boolean started = false;

        private OnReceivedListener onReceivedListener;

        byte[] abyte = new byte[64];

        public UDPRecv(DatagramSocket socket){
            this.socket = socket;
            packet = new DatagramPacket(abyte, 64);
        }

        @Override
        public void run() {
            super.run();
            started = true;
            while (true){
                try {
                    socket.receive(packet);
                    if(onReceivedListener != null){
                        onReceivedListener.onReceived(abyte, packet.getLength());
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        public void setOnReceivedListener(UDPRecv.OnReceivedListener onReceivedListener) {
            this.onReceivedListener = onReceivedListener;
        }

        public interface OnReceivedListener{
            void onReceived(byte[] bytes, int length);
        }
    }

    public static class UDPSend extends Thread implements Runnable{
        private DatagramSocket socket;
        private DatagramPacket packet;
        private WindSwingService service;

        byte[] abyte = new byte[64];

        public UDPSend(Context context, DatagramSocket socket){
            this.service = (WindSwingService) context;
            this.socket = socket;
            packet = new DatagramPacket(abyte, 64);
        }

        public void sendData(byte[] data, InetSocketAddress address){
            packet.setData(data);
            try {
                packet.setSocketAddress(address);
            }catch (IllegalArgumentException e){
                service.toast("参数错误", Toast.LENGTH_SHORT);
                return;
            }
            new Thread(this).start();
        }

        @Override
        public void run() {
            super.run();
            try {
                socket.send(packet);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}